package com.ding.easycontroller.file.impl;

import com.ding.easycontroller.file.PluginConfigFile;
import com.ding.easycontroller.file.PluginFilePathHolder;
import com.ding.easycontroller.plugin.PluginConfig;
import com.ding.easycontroller.utils.ElementUtils;
import com.ding.easycontroller.utils.FileUtils;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.XMLOutputter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;

import java.io.*;
import java.util.*;

@Component
public class PluginConfigFileImpl implements PluginConfigFile {


    @Autowired
    private XMLOutputter docWriter;

    private File configFile;

    PluginConfigFileImpl(PluginFilePathHolder holder) {
        File parent = holder.getRoot();
        File file = new File(parent, "config");
        if (!file.exists() && !file.mkdirs()) {
            throw new RuntimeException("路径创建失败" + file.getAbsolutePath());
        }

        configFile = new File(file, "config.xml");

        if (!configFile.exists()) {
            //将当前类路径下的默认的配置文件复制进该目录
            try {
                InputStream inputStream = new ClassPathResource("plugin/config.xml").getInputStream();
                FileOutputStream fileOutputStream = new FileOutputStream(configFile);
                FileUtils.copyStream(inputStream, fileOutputStream);
                inputStream.close();
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

    }

    private PluginConfig element2PluginConfig(Element element) {
        PluginConfig pluginConfig = new PluginConfig();

        Element name = element.getChild("name");
        if (name == null) {
            return null;
        }

        pluginConfig.setName(name.getText());

        Element enable = element.getChild("enable");

        if (enable != null) {
            pluginConfig.setEnable(true);
        }

        Element config = element.getChild("configs");

        if (config != null) {
            Map<String, String> conf = new HashMap<>();
            List<Element> children = config.getChildren();
            for (Element child : children) {
                if (child.getName().equals("config")) {
                    Element key = child.getChild("name");
                    Element value = child.getChild("value");
                    if (key != null && value != null) {
                        conf.put(key.getText(), value.getText());
                    }
                }
            }
            pluginConfig.setConfig(conf);
        }

        return pluginConfig;

    }

    Map<String, PluginConfig> configMap = new HashMap<>();

    @Override
    public Map<String, PluginConfig> loadConfigs() {
        Element root = ElementUtils.readElement(configFile);
        if (root == null || !root.getName().equals("plugins")) {
            return configMap;
        }
        List<Element> children = root.getChildren();
        for (Element child : children) {
            if (child.getName().equals("plugin")) {
                PluginConfig pluginConfig = element2PluginConfig(child);
                if (pluginConfig != null) {
                    configMap.put(pluginConfig.getName(), pluginConfig);
                }
            }
        }
        return configMap;
    }

    @Override
    public void updateConfig(PluginConfig config) {
        configMap.put(config.getName(), config);
        synchronize();
    }

    @Override
    public void addConfig(PluginConfig config) {
        configMap.put(config.getName(), config);
        synchronize();
    }

    private List<Element> config2element(Collection<PluginConfig> configs) {

        List<Element> r = new ArrayList<>();

        for (PluginConfig config : configs) {

            //创建一个元素
            Element element = new Element("plugin");

            Element name = new Element("name");
            name.setText(config.getName());
            element.getChildren().add(name);

            if (config.isEnable()) {
                element.getChildren().add(new Element("enable"));
            }

            if (config.getConfig() != null) {
                Map<String, String> c = config.getConfig();
                Element cf = new Element("configs");
                element.getChildren().add(cf);

                for (String s : c.keySet()) {
                    Element confige = new Element("config");
                    cf.getChildren().add(confige);
                    Element nE = new Element("name");
                    Element vE = new Element("value");
                    nE.setText(s);
                    vE.setText(c.get(s));
                    confige.getChildren().add(nE);
                    confige.getChildren().add(vE);
                }
            }

            r.add(element);

        }

        return r;
    }

    private void synchronize() {
        try {
            Document document = new Document();
            Element root = new Element("plugins");
            Collection<PluginConfig> configs = configMap.values();
            List<Element> elements = config2element(configs);
            for (Element element : elements) {
                root.getChildren().add(element);
            }
            document.setRootElement(root);
            String strFromXml = docWriter.outputString(document);
            FileWriter writer = new FileWriter(configFile);
            writer.write(strFromXml);
            writer.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}
